package com.kevms.phonewars;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

/** 
* @class WebService
* 
* @brief Interface to the external webservice
* 
* This Interface provides methods for sending
* webservice requests via the DefaultHttpClient.
*/ 
public class WebService {
	private static final String TAG = "WebService";
	public static final String URL_BASE = "http://pba.cs.clemson.edu/~kevin4/pw/";
	public static WebService mInstance = null;
	private DefaultHttpClient mHttpClient = null;
	private Context mContext;
	
	public static WebService getInstance(Context context) {
		if(mInstance == null) {
			mInstance = new WebService(context);
		}
		return mInstance;
	}
	
	private WebService(Context context) {
		this.mContext = context;
		mHttpClient = new DefaultHttpClient();
	}
	
	public void setSessionID(String sessionid) {
		CookieStore cookieStore = new BasicCookieStore();
		BasicClientCookie cookie = new BasicClientCookie("PHPSESSID", sessionid);
		cookie.setDomain("pba.cs.clemson.edu");
		cookie.setPath("/");
		cookieStore.addCookie(cookie);
		mHttpClient.setCookieStore(cookieStore);
	}
	
	private void showToast(String msg) {
		Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show();
	}
	
	private StringBuilder inputStreamToString(InputStream is) {
	    String line = "";
	    StringBuilder total = new StringBuilder();
	    
	    // Wrap a BufferedReader around the InputStream
	    BufferedReader rd = new BufferedReader(new InputStreamReader(is));

	    // Read response until the end
	    try {
			while ((line = rd.readLine()) != null) { 
			    total.append(line); 
			}
		} catch (IOException e) {
			showToast(e.toString());
		}
	    
	    // Return full string
	    return total;
	}
	
	private String sendPost(String path, List<NameValuePair> postData) throws Exception {
		
		HttpPost httppost = new HttpPost(path);
		JSONObject jObject = null;
		StringBuilder sb = null;
		
		try {
			// Add post data
			httppost.setEntity(new UrlEncodedFormEntity(postData));

			// Execute HTTP Post Request
			HttpResponse response = mHttpClient.execute(httppost);

			// Receive HTTP Reply
			InputStream is = response.getEntity().getContent();
			sb = inputStreamToString(is);
			is.close();
			
			jObject = new JSONObject(sb.toString());
			
			// Check for errors
			if(jObject.has("PW_ERROR")) {
				showToast(jObject.getString("PW_ERROR"));
			} else if(jObject.has("PW_SUCCESS")) {
				return jObject.getString("PW_SUCCESS");
			}
		} catch (Exception e) {
			throw new Exception("WebService: " + sb.toString());
		}
		
		throw new Exception("WebService: error");
	}
	
	public void logout() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "LOGOUT"));
		
		sendPost(URL_BASE+"pw_command.php", nameValuePairs);
	}
	
	public JSONObject setName(String name) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "SET_NAME"));
		nameValuePairs.add(new BasicNameValuePair("name", name));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}
	
	public JSONObject getName() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "GET_NAME"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}

	public JSONObject getId() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "GET_ID"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}
	
	public JSONArray getMatchList() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "GET_MATCHES"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONObject getMatch(String matchID) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "GET_MATCH"));
		nameValuePairs.add(new BasicNameValuePair("match_id", matchID));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}
	
	public JSONArray getMatchTypeDefaults() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "GET_MATCH_TYPE_DEFAULTS"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONArray joinMatch(String matchID) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "JOIN_MATCH"));
		nameValuePairs.add(new BasicNameValuePair("match_id", matchID));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONObject createMatchDM(ArrayList<String> data) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "CREATE_MATCH_DM"));
		nameValuePairs.add(new BasicNameValuePair("match_name", data.get(0)));
		nameValuePairs.add(new BasicNameValuePair("max_players", data.get(1)));
		nameValuePairs.add(new BasicNameValuePair("gun_radius", data.get(2)));
		nameValuePairs.add(new BasicNameValuePair("gun_range", data.get(3)));
		nameValuePairs.add(new BasicNameValuePair("dm_max_points", data.get(4)));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}
	
	public JSONArray updatePosition(Double latitude, Double longitude) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_POSITION"));
		nameValuePairs.add(new BasicNameValuePair("latitude", latitude.toString()));
		nameValuePairs.add(new BasicNameValuePair("longitude", longitude.toString()));
		
		Log.d(TAG, "update: "+latitude.toString()+","+longitude.toString());
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONArray updateGunShot(Double x, Double y) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_GUN_SHOT"));
		nameValuePairs.add(new BasicNameValuePair("x", x.toString()));
		nameValuePairs.add(new BasicNameValuePair("y", y.toString()));
		
		Log.d(TAG, "update: "+x.toString()+","+y.toString());
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONArray updateMineLay() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_MINE_LAY"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}

	public JSONArray updateMineDetonate() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_MINE_DETONATE"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONArray leaveMatch() throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_LEAVE_MATCH"));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONArray(s);
	}
	
	public JSONObject deleteMatch(String matchID) throws Exception {
		// Add post data
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
		nameValuePairs.add(new BasicNameValuePair("PW_COMMAND", "UPDATE_DELETE_MATCH"));
		nameValuePairs.add(new BasicNameValuePair("match_id", matchID));
		
		String s = sendPost(URL_BASE+"pw_command.php", nameValuePairs);
		return new JSONObject(s);
	}
}
